{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7f380157-7ab4-4aa3-8d45-6551a7e90fcb",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Downloading http://yann.lecun.com/exdb/mnist/train-images-idx3-ubyte.gz\n",
      "Failed to download (trying next):\n",
      "HTTP Error 403: Forbidden\n",
      "\n",
      "Downloading https://ossci-datasets.s3.amazonaws.com/mnist/train-images-idx3-ubyte.gz\n",
      "Downloading https://ossci-datasets.s3.amazonaws.com/mnist/train-images-idx3-ubyte.gz to ./data\\MNIST\\raw\\train-images-idx3-ubyte.gz\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "100%|██████████| 9.91M/9.91M [00:13<00:00, 713kB/s] \n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Extracting ./data\\MNIST\\raw\\train-images-idx3-ubyte.gz to ./data\\MNIST\\raw\n",
      "\n",
      "Downloading http://yann.lecun.com/exdb/mnist/train-labels-idx1-ubyte.gz\n",
      "Failed to download (trying next):\n",
      "HTTP Error 403: Forbidden\n",
      "\n",
      "Downloading https://ossci-datasets.s3.amazonaws.com/mnist/train-labels-idx1-ubyte.gz\n",
      "Downloading https://ossci-datasets.s3.amazonaws.com/mnist/train-labels-idx1-ubyte.gz to ./data\\MNIST\\raw\\train-labels-idx1-ubyte.gz\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "100%|██████████| 28.9k/28.9k [00:00<00:00, 118kB/s]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Extracting ./data\\MNIST\\raw\\train-labels-idx1-ubyte.gz to ./data\\MNIST\\raw\n",
      "\n",
      "Downloading http://yann.lecun.com/exdb/mnist/t10k-images-idx3-ubyte.gz\n",
      "Failed to download (trying next):\n",
      "HTTP Error 403: Forbidden\n",
      "\n",
      "Downloading https://ossci-datasets.s3.amazonaws.com/mnist/t10k-images-idx3-ubyte.gz\n",
      "Downloading https://ossci-datasets.s3.amazonaws.com/mnist/t10k-images-idx3-ubyte.gz to ./data\\MNIST\\raw\\t10k-images-idx3-ubyte.gz\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "100%|██████████| 1.65M/1.65M [00:01<00:00, 986kB/s] \n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Extracting ./data\\MNIST\\raw\\t10k-images-idx3-ubyte.gz to ./data\\MNIST\\raw\n",
      "\n",
      "Downloading http://yann.lecun.com/exdb/mnist/t10k-labels-idx1-ubyte.gz\n",
      "Failed to download (trying next):\n",
      "HTTP Error 403: Forbidden\n",
      "\n",
      "Downloading https://ossci-datasets.s3.amazonaws.com/mnist/t10k-labels-idx1-ubyte.gz\n",
      "Downloading https://ossci-datasets.s3.amazonaws.com/mnist/t10k-labels-idx1-ubyte.gz to ./data\\MNIST\\raw\\t10k-labels-idx1-ubyte.gz\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "100%|██████████| 4.54k/4.54k [00:00<00:00, 4.49MB/s]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Extracting ./data\\MNIST\\raw\\t10k-labels-idx1-ubyte.gz to ./data\\MNIST\\raw\n",
      "\n",
      "Epoch 1, Loss: 0.3397\n",
      "Epoch 2, Loss: 0.1538\n",
      "Epoch 3, Loss: 0.1114\n",
      "Epoch 4, Loss: 0.0884\n",
      "Epoch 5, Loss: 0.0755\n",
      "MNIST Test set: Average loss: 0.1067, Accuracy: 96.84%\n"
     ]
    }
   ],
   "source": [
    "import torch\n",
    "import torch.nn as nn\n",
    "import torch.optim as optim\n",
    "from torchvision import datasets, transforms\n",
    "from torch.utils.data import DataLoader\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "# 定义全连接神经网络\n",
    "class FNN(nn.Module):\n",
    "    def __init__(self, input_size, hidden_sizes, output_size):\n",
    "        super(FNN, self).__init__()\n",
    "        layers = []\n",
    "        for i in range(len(hidden_sizes)):\n",
    "            layers.append(nn.Linear(input_size if i == 0 else hidden_sizes[i-1], hidden_sizes[i]))\n",
    "            layers.append(nn.ReLU())\n",
    "        layers.append(nn.Linear(hidden_sizes[-1], output_size))\n",
    "        self.model = nn.Sequential(*layers)\n",
    "\n",
    "    def forward(self, x):\n",
    "        return self.model(x)\n",
    "\n",
    "# 数据预处理\n",
    "transform = transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.5,), (0.5,))])\n",
    "\n",
    "# 加载MNIST数据集\n",
    "train_dataset = datasets.MNIST(root='./data', train=True, download=True, transform=transform)\n",
    "train_loader = DataLoader(dataset=train_dataset, batch_size=64, shuffle=True)\n",
    "\n",
    "test_dataset = datasets.MNIST(root='./data', train=False, download=True, transform=transform)\n",
    "test_loader = DataLoader(dataset=test_dataset, batch_size=64, shuffle=False)\n",
    "\n",
    "# 假设Wi-Fi动作感知数据集加载\n",
    "# wifi_dataset = ...  # 您需要替换为实际的Wi-Fi动作感知数据集加载代码\n",
    "# wifi_loader = DataLoader(dataset=wifi_dataset, batch_size=64, shuffle=False)\n",
    "\n",
    "# 模型训练和评估\n",
    "device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n",
    "model = FNN(input_size=784, hidden_sizes=[256, 128], output_size=10).to(device)\n",
    "criterion = nn.CrossEntropyLoss()\n",
    "optimizer = optim.Adam(model.parameters(), lr=0.001)\n",
    "\n",
    "# 训练循环\n",
    "def train(model, device, train_loader, criterion, optimizer, epochs):\n",
    "    model.train()\n",
    "    total_losses = []\n",
    "    for epoch in range(epochs):\n",
    "        total_loss = 0\n",
    "        for data, target in train_loader:\n",
    "            data, target = data.to(device), target.to(device)\n",
    "            optimizer.zero_grad()\n",
    "            output = model(data.view(-1, 784))  # Flatten the images\n",
    "            loss = criterion(output, target)\n",
    "            loss.backward()\n",
    "            optimizer.step()\n",
    "            total_loss += loss.item()\n",
    "        total_losses.append(total_loss / len(train_loader))\n",
    "        print(f'Epoch {epoch+1}, Loss: {total_loss / len(train_loader):.4f}')\n",
    "    return total_losses\n",
    "\n",
    "# 训练模型\n",
    "total_losses = train(model, device, train_loader, criterion, optimizer, epochs=5)\n",
    "\n",
    "# 测试模型\n",
    "def test(model, device, test_loader, criterion):\n",
    "    model.eval()\n",
    "    test_loss = 0\n",
    "    correct = 0\n",
    "    with torch.no_grad():\n",
    "        for data, target in test_loader:\n",
    "            data, target = data.to(device), target.to(device)\n",
    "            output = model(data.view(-1, 784))  # Flatten the images\n",
    "            test_loss += criterion(output, target).item()\n",
    "            pred = output.argmax(dim=1, keepdim=True)\n",
    "            correct += pred.eq(target.view_as(pred)).sum().item()\n",
    "\n",
    "    test_loss /= len(test_loader)\n",
    "    accuracy = 100. * correct / len(test_loader.dataset)\n",
    "    return test_loss, accuracy\n",
    "\n",
    "# 测试MNIST数据集\n",
    "test_loss, test_accuracy = test(model, device, test_loader, criterion)\n",
    "print(f'MNIST Test set: Average loss: {test_loss:.4f}, Accuracy: {test_accuracy:.2f}%')\n",
    "\n",
    "# 测试Wi-Fi动作感知数据集\n",
    "# wifi_test_loss, wifi_test_accuracy = test(model, device, wifi_loader, criterion)\n",
    "# print(f'Wi-Fi Action Recognition Test set: Average loss: {wifi_test_loss:.4f}, Accuracy: {wifi_test_accuracy:.2f}%')\n",
    "\n",
    "# 绘制学习曲线\n",
    "def plot_learning_curve(train_losses, filename):\n",
    "    plt.figure(figsize=(10, 5))\n",
    "    plt.plot(train_losses, label='Training Loss')\n",
    "    plt.title('Learning Curve')\n",
    "    plt.xlabel('Epochs')\n",
    "    plt.ylabel('Loss')\n",
    "    plt.legend()\n",
    "    plt.savefig(filename)\n",
    "    plt.show()\n",
    "\n",
    "plot_learning_curve(total_losses, '图3_学习曲线.png')\n",
    "\n",
    "# 绘制和保存手写字母识别结果\n",
    "def plot_accuracy(accuracy, title, filename):\n",
    "    plt.figure(figsize=(8, 6))\n",
    "    plt.bar(['Accuracy'], [accuracy])\n",
    "    plt.title(title)\n",
    "    plt.ylabel('Accuracy (%)')\n",
    "    plt.savefig(filename)\n",
    "    plt.show()\n",
    "\n",
    "plot_accuracy(test_accuracy, 'MNIST Handwritten Digit Recognition Accuracy', '图1_手写字母识别结果.png')\n",
    "# plot_accuracy(wifi_test_accuracy, 'Wi-Fi Action Recognition Accuracy', '图2_Wi-Fi动作感知结果.png')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0c31eb7c-4e2c-4224-9715-ec5230132f0f",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
